package com.whately.core.base.utils.http;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;

/**
 * http 请求util
 * 1.发送短信
 * 2.请求天眼查
 */
public class HttpClientUtil {

	private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

	private final static Integer CONNECT_TIME_OUT = 10 * 1000;

	private final static Integer CONNECT_REQUEST_TIME_OUT = 5 * 1000;

	private final static Integer SOCKET_TIME_OUT = 30 * 1000;

	private final static String ASK = "?";

	private final static String AND = "&";

	  private final static String UTF8 = "UTF-8";

	    private final static String APPLICATION_JSON = "application/json; charset=UTF-8";

	private static CloseableHttpClient fetchHttpClient(){
		RequestConfig defaultRequestConfig = RequestConfig
				.custom()
				.setSocketTimeout(SOCKET_TIME_OUT.intValue())
				.setConnectTimeout(CONNECT_TIME_OUT.intValue())
				.setConnectionRequestTimeout(CONNECT_REQUEST_TIME_OUT.intValue()).build();
		CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();
		return client;
	}

	public static String doget(final String uri, final Map<String, String> content,final Map<String, String> header) {
		String strResult = "";

		CloseableHttpClient client = fetchHttpClient();
		StringBuilder url = new StringBuilder(uri);

		HttpGet get = null;
		if(content != null){
			url.append(ASK);
			for (Map.Entry<String, String> entry : content.entrySet()) {
				url.append(entry.getKey()+"="+entry.getValue()+AND);
			}
			get = new HttpGet(url.toString().substring(0, url.length()-1));
		}else{
			get = new HttpGet(url.toString());
		}
		if (header != null) {
			for (Map.Entry<String, String> entry : header.entrySet()) {
				get.setHeader(entry.getKey(), entry.getValue());
			}
		}


		try {
			CloseableHttpResponse response = client.execute(get);
			int statusCode = response.getStatusLine().getStatusCode();
			if (200 == statusCode) {
				//中文编码问题
				strResult = new String(EntityUtils.toByteArray(response.getEntity()), UTF8);
//				strResult = EntityUtils.toString(response.getEntity()).trim();
			} else {
				logger.error("|HttpClientUtil|doGet|error status|", statusCode);
			}
		} catch (IOException e) {
			logger.error("|HttpClientUtil|doGet|", e);
		} finally {
			if (get != null) {
				get.releaseConnection();
			}
			if (client != null) {
				try {
					client.close();
				} catch (IOException e) {
					logger.error("|HttpClientUtil|doGet|", e);
				}
			}
		}
		return strResult;
	}


	/**
	 * 发送post请求，参数用map接收
	 * @return 返回值
	 */
	public static String doPost(String uri,Map<String,String> mapParam, Map<String, String> header) {
		return doPost(uri,mapParam,header,UTF8);
	}

	public static String doPost(String uri,Map<String,String> mapParam, Map<String, String> header,String charset) {
		String strResult = "";
		CloseableHttpClient client = fetchHttpClient();
		HttpPost post = new HttpPost(uri);
		if (header != null) {
			for (Map.Entry<String, String> entry : header.entrySet()) {
				post.setHeader(entry.getKey(), entry.getValue());
			}
		}

		//设置参数发送
		List<NameValuePair> pairs = new ArrayList<NameValuePair>();
		if(mapParam!=null){
			for(Map.Entry<String,String> entry : mapParam.entrySet())
			{
				pairs.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));
			}
		}


		try {
			post.setEntity(new UrlEncodedFormEntity(pairs,charset));

			CloseableHttpResponse response = client.execute(post);
			int statusCode = response.getStatusLine().getStatusCode();
			if (200 == statusCode) {
				strResult = new String(EntityUtils.toByteArray(response.getEntity()), charset);
			} else {
				logger.error("|HttpClientUtil|doPostMap|error status|", statusCode);
			}

		}  catch (Exception e) {
			logger.error("|HttpClientUtil|doPostMap|", e);
		}finally {
			if (post != null) {
				post.releaseConnection();
			}
			if (client != null) {
				try {
					client.close();
				} catch (IOException e) {
					logger.error("|HttpClientUtil|doPostMap|", e);
				}
			}
		}
		return strResult;
	}


	/**
	 * 使用httpclint 发送文件
	 * @author: qingfeng
	 * @date: 2019-05-27
	 * @param file
	 *            上传的文件
	 * @return 响应结果
	 */
	public static String postUploadFile(String url , MultipartFile file,  Map<String,String> headerParams, Map<String,String> otherParams) {
		String receiveFileName = "file";
		return postUploadFile(url,file,receiveFileName,headerParams,otherParams);
	}

	public static String postUploadFile(String url , MultipartFile file, String receiveFileName, Map<String,String> headerParams, Map<String,String> otherParams) {
		CloseableHttpClient client = fetchHttpClient();
		String result = "";
		HttpPost post = new HttpPost(url);

		try {
			String fileName = file.getOriginalFilename();

			//添加header
			if(headerParams!=null){
				for (Map.Entry<String, String> e : headerParams.entrySet()) {
					post.addHeader(e.getKey(), e.getValue());
				}
			}

			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
			builder.setCharset(Charset.forName(UTF8));
			builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//加上此行代码解决返回中文乱码问题
			builder.addBinaryBody(StringUtils.isBlank(receiveFileName)?"file":receiveFileName.trim(), file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流

			if(otherParams!=null){
				for (Map.Entry<String, String> e : otherParams.entrySet()) {
					builder.addTextBody(e.getKey(), e.getValue());// 类似浏览器表单提交，对应input的name和value
				}
			}

			HttpEntity entity = builder.build();
			post.setEntity(entity);
			CloseableHttpResponse response = client.execute(post);// 执行提交

			int statusCode = response.getStatusLine().getStatusCode();
			if (200 == statusCode) {
				result = new String(EntityUtils.toByteArray(response.getEntity()), UTF8);
			} else {
				logger.error("|HttpClientUtil|doPostMap|error status|", statusCode);
			}

		} catch (IOException e) {
			logger.error("|HttpClientUtil|postUploadFile|", e);
		} catch (Exception e) {
			logger.error("|HttpClientUtil|postUploadFile|", e);
		} finally {
			if (post != null) {
				post.releaseConnection();
			}
			if (client != null) {
				try {
					client.close();
				} catch (IOException e) {
					logger.error("|HttpClientUtil|doPostMap|", e);
				}
			}
		}
		return result;
	}


	/*
	 public static String doPost(final String uri, final String args, Map<String, String> header) {
	        String strResult = "";
	        RequestConfig defaultRequestConfig = RequestConfig.custom()
	                .setSocketTimeout(SOCKET_TIME_OUT.intValue())
	                .setConnectTimeout(CONNECT_TIME_OUT.intValue())
	                .setConnectionRequestTimeout(CONNECT_REQUEST_TIME_OUT.intValue())
	                .build();
	        CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();
	        HttpPost post = new HttpPost(uri);
	        if (header != null) {
	            for (Map.Entry<String, String> entry : header.entrySet()) {
	                post.setHeader(entry.getKey(), entry.getValue());
	            }
	        }

	        StringEntity se = null;
	        try {
	            se = new StringEntity(args, UTF8);
	        } catch (Exception e) {
	            logger.error("|HttpClientUtil|doPost|", e);
	        }
	        //se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON));
	        //se.setContentType(APPLICATION_JSON);
	        post.setEntity(se);
	        CloseableHttpResponse response = null;
	        try {
	            response = client.execute(post);
	            int statusCode = response.getStatusLine().getStatusCode();
	            if (200 == statusCode) {
	                strResult = new String(EntityUtils.toByteArray(response.getEntity()), UTF8);
	            } else {
	                logger.error("|HttpClientUtil|doPost|error status|", statusCode);
	            }
	        } catch (IOException e) {
	            logger.error("|HttpClientUtil|doPost|", e);
	        } finally {
	            if (post != null) {
	                post.releaseConnection();
	            }
	            if (client != null) {
	            	try {
						client.close();
					} catch (IOException e) {
						logger.error("|HttpClientUtil|doPost|", e);
					}
	            }
	        }
	        return strResult;
	    }

	 */

	 public static String doJsonPost(final String uri, final String args) {
	        String strResult = "";
	        RequestConfig defaultRequestConfig = RequestConfig.custom()
	                .setSocketTimeout(SOCKET_TIME_OUT.intValue())
	                .setConnectTimeout(CONNECT_TIME_OUT.intValue())
	                .setConnectionRequestTimeout(CONNECT_REQUEST_TIME_OUT.intValue())
	                .build();
	        CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();
	        HttpPost post = new HttpPost(uri);

	        StringEntity se = null;
	        try {
	            se = new StringEntity(args, UTF8);
	        } catch (Exception e) {
	            logger.error("|HttpClientUtil|opentsdbPut|", e);
	        }
	        se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON));
	        se.setContentType(APPLICATION_JSON);
	        post.setEntity(se);
	        CloseableHttpResponse response = null;
	        try {
	            response = client.execute(post);
	            int statusCode = response.getStatusLine().getStatusCode();
	            if (204 != statusCode) {
	                logger.error("|HttpClientUtil|opentsdbPut|error status|", statusCode);
	            }
	        } catch (IOException e) {
	            logger.error("|HttpClientUtil|opentsdbPut|", e);
	        } finally {
	            if (post != null) {
	                post.releaseConnection();
	            }
	            if (client != null) {
	            	try {
						client.close();
					} catch (IOException e) {
						logger.error("|HttpClientUtil|opentsdbPut|", e);
					}
	            }
	        }
	        return strResult;
	    }

	 /**
     * main函数.
     * @param args
     *            启动参数
     * @throws Exception
     *             Exception
     */
    public static void main(String... args) throws Exception {
    	final String plainCreds = "";
    	final byte[] plainCredsBytes = plainCreds.getBytes();
    	final byte[] base64CredsBytes = Base64.getEncoder().encode(plainCredsBytes);
    	final String base64Creds = new String(base64CredsBytes);
    	Map<String,String> map = new HashMap<String,String>();
    	map.put("Authorization", "Basic "+ base64Creds);

    	String result = doget("http://", null, map);
    	System.out.println(result);
    }

    public static String getRemortIP(HttpServletRequest request) {
		if (request.getHeader("x-forwarded-for") == null) {
			return request.getRemoteAddr();
		}
		return request.getHeader("x-forwarded-for");
	}
}
